#include "stdafx.h"

#include <iostream>
#include <string>
#include <list>
#include <fstream>
#include <algorithm>

#include "SearcheableHTMLFile.h"



SearcheableHTMLFile::SearcheableHTMLFile(std::string& fileName)
{
	this->fileName = fileName;
}

SearcheableHTMLFile::~SearcheableHTMLFile()
{
}

std::set<std::string>* SearcheableHTMLFile::search(std::set<std::string>& wordSet, struct searchParameters params)
{
	using namespace std;

	set<string>* foundWords = new set<string>(); // caller should delete	

	if(!wordSet.empty())
	{		
		HANDLE file = openFile(this->fileName);		

		if(file != NULL)
		{			
			int count;
			string nextWord;
			int currWordLength = 0;
			bool lookForNextSpace = false;
			
			bool allWordsFound = false;

			int tagCount = 0;
 
			while((count = readInBuffer(file, ISearcheableFile::buffer)) > 0) 
			{				
				for(int i = 0; i < count; i++)
				{
					char currSymbol = buffer[i];

					if(currSymbol == LEFT_TAG)
					{		
						if(tagCount == 0)
						{
							if(currWordLength >= params.minWordLength) 
							{
								boost::algorithm::to_lower(nextWord);
								if(checkInWord(nextWord, wordSet, *foundWords))
								{
									allWordsFound = true;
									break;
								}
							}

							nextWord = "";
							currWordLength = 0;
							lookForNextSpace = false;
						}
						tagCount++;
						continue;
					}

					if(currSymbol == RIGHT_TAG)
					{
						if(tagCount > 0)
						{
							tagCount--;
						}
						continue;
					}

					if(tagCount != 0)
					{
						continue;
					}

					if(lookForNextSpace)
					{
						if(currSymbol == WORD_SEPARATOR)
						{
							lookForNextSpace = false;
						}
						continue;
					}						

					if(currSymbol == WORD_SEPARATOR)
					{
						if(currWordLength >= params.minWordLength) 
						{
							boost::algorithm::to_lower(nextWord);
							if(checkInWord(nextWord, wordSet, *foundWords))
							{
								allWordsFound = true;
								break;
							}
						}
						nextWord = "";
						currWordLength = 0;
						continue;
					}

					nextWord += currSymbol;
					currWordLength++;

					if(currWordLength < params.minWordLength)
					{
						continue;
					}

					if(currWordLength == params.maxWordLength + 1)
					{
						nextWord = "";
						currWordLength = 0;
						lookForNextSpace = true;
					}
				}

				if(allWordsFound)
				{
					break;
				}
			}

			if(!allWordsFound && !nextWord.empty())
			{
				boost::algorithm::to_lower(nextWord);
				checkInWord(nextWord, wordSet, *foundWords);
			}
		}		
		CloseHandle(file);
	}

	return foundWords;
}


void SearcheableHTMLFile::searchForIndexing(
		struct searchParameters params, std::set<int>* indexes, IndexMap* indexMap)
{
	using namespace std;		
			
	HANDLE file = openFile(this->fileName);		

	if(file != NULL)
	{
		int count;
		string nextWord;
		int currWordLength = 0;
		bool lookForNextSpace = false;

		//bool allWordsFound = false;

		int tagCount = 0;

		while((count = readInBuffer(file, ISearcheableFile::buffer)) > 0) 
		{				
			for(int i = 0; i < count; i++)
			{
				char currSymbol = buffer[i];

				if(currSymbol == LEFT_TAG)
				{		
					if(tagCount == 0)
					{
						if(currWordLength >= params.minWordLength) 
						{							
							boost::algorithm::to_lower(nextWord);
							indexMap->addWord(nextWord, this->fileName, *indexes);
						}

						nextWord = "";
						currWordLength = 0;
						lookForNextSpace = false;
					}
					tagCount++;
					continue;
				}

				if(currSymbol == RIGHT_TAG)
				{
					if(tagCount > 0)
					{
						tagCount--;
					}
					continue;
				}

				if(tagCount != 0)
				{
					continue;
				}

				if(lookForNextSpace)
				{
					if(currSymbol == WORD_SEPARATOR)
					{
						lookForNextSpace = false;
					}
					continue;
				}						

				if(currSymbol == WORD_SEPARATOR)
				{
					if(currWordLength >= params.minWordLength) 
					{
						boost::algorithm::to_lower(nextWord);
						indexMap->addWord(nextWord, this->fileName, *indexes);
					}
					nextWord = "";
					currWordLength = 0;
					continue;
				}

				nextWord += currSymbol;
				currWordLength++;

				if(currWordLength < params.minWordLength)
				{
					continue;
				}

				if(currWordLength == params.maxWordLength + 1)
				{
					nextWord = "";
					currWordLength = 0;
					lookForNextSpace = true;
				}
			}
		}

		if(!nextWord.empty())
		{
			boost::algorithm::to_lower(nextWord);
			indexMap->addWord(nextWord, this->fileName, *indexes);
		}
	}

	CloseHandle(file);	
}


void SearcheableHTMLFile::buildIndex(IndexMap* indexMap)
{
	using namespace std;

	searchParameters searchParams;

	searchParams.minWordLength = 1;
	searchParams.maxWordLength = 200;

	set<int>* indexes = indexMap->getIndex(this->fileName);
	
	searchForIndexing(searchParams, indexes, indexMap);
}